package com.xique.door.device.command;

import com.alibaba.fastjson.JSONObject;
import com.xique.common.core.utils.DateUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.door.bean.domain.AccessDevice;
import com.xique.door.bean.domain.DCard;
import com.xique.door.bean.domain.User;
import com.xique.door.bean.domain.Visitor;
import com.xique.door.bean.domain.estate.EstateUser;
import com.xique.door.bean.dto.CardDeviceHouseCodeDTO;
import com.xique.door.bean.dto.EstateUserDownDTO;
import com.xique.door.bean.dto.UserDeviceHouseCodeDTO;
import com.xique.door.constant.AccessCommandConstant;
import com.xique.door.constant.AccessServiceName;
import com.xique.door.constant.ApiConstant;
import com.xique.door.device.hq.bean.dto.HQDeviceUserInfoDto;
import com.xique.door.device.hq.bean.dto.HQInfoDTO;
import com.xique.door.device.hq.bean.dto.HQOpenDoorInfoDTO;
import com.xique.door.service.IBuildHouseUserService;
import com.xique.door.service.IUserService;
import com.xique.door.util.RestTemplateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class AccessCommandHQService {

    @Value("${ruoyi.faceApiUrl}")
    private String apiUrl;

    @Value("${HQ_DEFAULT_PIC}")
    private String hqDefaultPic;

    @Autowired
    private RestTemplateUtils restTemplateUtils;

    @Autowired
    private IUserService userService;
    @Autowired
    private IBuildHouseUserService buildHouseUserService;


    private JSONObject getBaseObj(String serviceName, String version) {
        JSONObject obj = new JSONObject();
        obj.put("charset", "UTF-8");
        obj.put("service", serviceName);
        obj.put("version", version);
        obj.put("sign", "sign");
        return obj;
    }

    /**
     * 多个设备下载用户信息
     *
     * @return
     */
    public Object downBatchUserInfos(List<AccessDevice> accessDevices, List<User> users, List<UserDeviceHouseCodeDTO> dtos) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = transferHQDeviceUserDTO(accessDevices, users, dtos);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    public Object downBatchVisitorInfos(List<AccessDevice> accessDevices, List<Visitor> visitors) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = transferHQDeviceVisitorDTO(accessDevices, visitors);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    public Object downBatchCardInfos(List<AccessDevice> accessDevices, List<DCard> cards, List<CardDeviceHouseCodeDTO> dtos) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload,  AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = transferHQCardInfoDTOV1(accessDevices, cards, dtos);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * 单个设备下载用户信息
     *
     * @return
     */
    public Object downCardInfos(List<String> deviceSns, User user, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUserDownload, version);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        String floorCode = buildHouseUserService.selectHqFloorCodeByUser(user);
        user.setFloorCode(floorCode);
        dataObj.put("info", transferHQInfoDTO(user));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 下发卡
     * @author caogq
     * @date: 2022/3/18 19:22
     * @Param
     */
    public Object downCardInfos(List<String> devSns, User user, DCard dCard,List<CardDeviceHouseCodeDTO> dtos) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload,  AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", devSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
//        String floorCode = buildHouseUserService.selectHqFloorCodeByCard(dCard);
//        user.setFloorCode(floorCode);
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = transferHQCardInfoDTO(devSns, user, dCard, dtos);
        dataObj.put("info", JSONObject.toJSONString(hqDeviceUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * 多个设备下载用户卡片信息（此处下发的时候，不重新下发人脸）
     *
     * @return
     */
    public Object downBatchDCardInfos(List<String> deviceSns, List<DCard> cards, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, version);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQInfoDTO> dtos = new ArrayList<>();
        Map<String, Object> cardFloorCodeMap = buildHouseUserService.batchSelectHqFloorCodeByCards(cards);
        cards.stream().forEach(card -> {
            Object o = cardFloorCodeMap.get(card.getId());
            card.setFloorCode(o != null ? o.toString() : "");
            HQInfoDTO dto = transferHQInfoDTO(card);
            dtos.add(dto);
        });
        /***增加卡片信息的下发****/
        dataObj.put("info", dtos);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * 单个设备下载用户信息
     *
     * @return
     */
    public Object downVisitorInfos(List<String> deviceSns, Visitor visitor, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUserDownload, version);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        dataObj.put("info", transferHQInfoDTO(visitor));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * 海清人员信息下发数据打包
     *
     * @param user
     * @return
     */
    private HQInfoDTO transferHQInfoDTO(User user) {
        HQInfoDTO dto = new HQInfoDTO();
        dto.setCustomId(user.getCustomId());
        dto.setName(user.getUserName());
        dto.setPersonType(user.getPersonType());
        dto.setTempCardType(Integer.parseInt(user.getVisitorType()));
        dto.setPicURI(user.getFaceUrl());
        dto.setAddress(user.getFloorCode());
        return dto;
    }

    private List<HQDeviceUserInfoDto> transferHQDeviceUserDTO(List<AccessDevice> accessDevices, List<User> users, List<UserDeviceHouseCodeDTO> dtos) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (User user : users) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(user.getCustomId());
                dto.setName(user.getUserName());
                dto.setPersonType(user.getPersonType());
                //0永久名单
                dto.setTempCardType(StringUtils.isNotEmpty(user.getVisitorType()) ? Integer.parseInt(user.getVisitorType()) : 0);
                dto.setPicURI(user.getFaceUrl());
                dto.setAddress("");
                if (!dtos.isEmpty()){
                    List<String> floorCodes = dtos.stream()
                            .filter(e -> e.getDeviceId().equals(accessDevice.getId()) && e.getUserId().equals(user.getId()))
                            .map(UserDeviceHouseCodeDTO::getHouseCode)
                            .collect(Collectors.toList());
                    String floorCode = "";
                    if ("5".equals(user.getType()) || "6".equals(user.getType())) {
                        //保洁梯控全开
                        floorCode = "8,40";
                    }
                    if ((!floorCodes.isEmpty() && floorCodes.size() == 1)) {
                        //单楼层 直接上传楼层好
                        floorCode = floorCodes.get(0).substring(0, 2);
                    } else if (!floorCodes.isEmpty() && floorCodes.size() > 1) {
                        List<String> newCodes = floorCodes.stream().map(e -> e.substring(0, 2)).collect(Collectors.toList());
                        //多楼层，8：保持时间，size：楼层数量 code：具体楼层用/分割， 例如 8,3-1/9/10
                        floorCode = 8 + "," + floorCodes.size() + "," + StringUtils.join(newCodes, "/");
                    }
                    dto.setAddress(floorCode);
                }
                hqInfoDTOS.add(dto);
            }
            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }
        return hqDeviceUserInfoDtos;
    }

    private List<HQDeviceUserInfoDto> transferHQDeviceVisitorDTO(List<AccessDevice> accessDevices, List<Visitor> visitors) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (Visitor visitor : visitors) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(visitor.getCustomId());
                dto.setName(visitor.getVisitorName());
                dto.setPersonType(visitor.getPersonType());
                dto.setTempCardType(Integer.parseInt(visitor.getVisitorType()));
                if ("1".equals(visitor.getVisitorType()) || "2".equals(visitor.getVisitorType())) {
                    dto.setCardValidBegin(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, visitor.getStartTime()));
                    dto.setCardValidEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, visitor.getEndTime()));
                } else if ("3".equals(visitor.getVisitorType())) {
                    dto.setEffectNumber(Math.toIntExact(visitor.getEffectNumber()));
                }
                dto.setPicURI(visitor.getFaceUrl());
                dto.setAddress("");
                if (StringUtils.isNotEmpty(visitor.getHouseCode())) {
                    dto.setAddress(visitor.getHouseCode().substring(0, 2));
                }
                hqInfoDTOS.add(dto);
            }
            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }
        return hqDeviceUserInfoDtos;
    }
    /**
     * 海清人员信息下发数据打包（卡片）
     * 下发的时候，人脸等都下发。一般第一次下发需要都发下去
     *
     * @param user
     * @return
     */
    private List<HQDeviceUserInfoDto> transferHQCardInfoDTO(List<String> devSns,User user, DCard dCard,List<CardDeviceHouseCodeDTO> dtos) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (String devSn : devSns) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            hqDeviceUserInfoDto.setDeviceCode(devSn);
            HQInfoDTO dto = new HQInfoDTO();
            dto.setCustomId(dCard.getCustomId());
            dto.setName(user.getUserName());
            dto.setPersonType(user.getPersonType());
            if (StringUtils.isNotEmpty(user.getFaceUrl())) {
                dto.setPicURI(user.getFaceUrl());
            } else {
                dto.setPicURI(hqDefaultPic);
            }
            if (dCard.getIsLoss() == null || dCard.getIsLoss() == false){
                dto.setRFIDCard(dCard.getCardSn());
            }else {
                dto.setRFIDCard("0000000000");
            }
            dto.setRFCardMode(0);
            if (null != dCard.getDoorEndDate()) {
                //时间段有效
                dto.setTempCardType(1);
                dto.setCardValidBegin(null != dCard.getDoorBeginDate() ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dCard.getDoorBeginDate()) : null);
                dto.setCardValidEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dCard.getDoorEndDate()));
            } else {
                dto.setTempCardType(0);
            }
            List<String> floorCodes = dtos.stream().filter(e -> e.getDevSn().equals(devSn) && e.getCardSn().equals(dCard.getCardSn())).map(CardDeviceHouseCodeDTO::getHouseCode).collect(Collectors.toList());
            String floorCode = "";
            if ("5".equals(dCard.getCardType()) || "6".equals(dCard.getCardType())) {
                //保洁梯控全开
                floorCode = "8,40";
            }else if ((!floorCodes.isEmpty() && floorCodes.size() == 1)) {
                //单楼层 直接上传楼层好
                floorCode = floorCodes.get(0).substring(0, 2);
            } else if (!floorCodes.isEmpty() && floorCodes.size() > 1) {
                List<String> newCodes = floorCodes.stream().map(e -> e.substring(0, 2)).collect(Collectors.toList());
                //多楼层，8：保持时间，size：楼层数量 code：具体楼层用/分割， 例如 8,3-1/9/10
                floorCode = 8 + "," + floorCodes.size() + "," + StringUtils.join(newCodes, "/");
            }
            dto.setAddress(floorCode);
            hqDeviceUserInfoDto.setHqInfoDtos(Collections.singletonList(dto));
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }

        return hqDeviceUserInfoDtos;
    }

    /**
     * 海清人员信息下发数据打包（卡片）
     * 下发的时候，人脸等都下发。一般第一次下发需要都发下去
     *
     * @param cards
     * @return
     */
    private List<HQDeviceUserInfoDto> transferHQCardInfoDTOV1(List<AccessDevice> accessDevices, List<DCard> cards, List<CardDeviceHouseCodeDTO> dtos) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (DCard card : cards) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(card.getCustomId());
                dto.setName(card.getUserName());
                dto.setPersonType(card.getPersonType());
                dto.setPicURI(hqDefaultPic);
                if (card.getIsLoss() == null || card.getIsLoss() == false){
                    dto.setRFIDCard(card.getCardSn());
                }else {
                    dto.setRFIDCard("0000000000");
                }
                dto.setRFCardMode(0);
                if (null != card.getDoorEndDate()) {
                    //时间段有效
                    dto.setTempCardType(1);
                    dto.setCardValidBegin(null != card.getDoorBeginDate() ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, card.getDoorBeginDate()) : null);
                    dto.setCardValidEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, card.getDoorEndDate()));
                } else {
                    dto.setTempCardType(0);
                }
                List<String> floorCodes = dtos.stream().filter(e -> e.getDevSn().equals(accessDevice.getDevSn()) && e.getCardSn().equals(card.getCardSn())).map(CardDeviceHouseCodeDTO::getHouseCode).collect(Collectors.toList());
                String floorCode = "";
                if ("5".equals(card.getCardType()) || "6".equals(card.getCardType())) {
                    //保洁梯控全开
                    floorCode = "8,40";
                }else if ((!floorCodes.isEmpty() && floorCodes.size() == 1)) {
                    //单楼层 直接上传楼层好
                    floorCode = floorCodes.get(0).substring(0, 2);
                } else if (!floorCodes.isEmpty() && floorCodes.size() > 1) {
                    List<String> newCodes = floorCodes.stream().map(e -> e.substring(0, 2)).collect(Collectors.toList());
                    //多楼层，8：保持时间，size：楼层数量 code：具体楼层用/分割， 例如 8,3-1/9/10
                    floorCode = 8 + "," + floorCodes.size() + "," + StringUtils.join(newCodes, "/");
                }
                dto.setAddress(floorCode);
                hqInfoDTOS.add(dto);
            }

            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }

        return hqDeviceUserInfoDtos;
    }

    /**
     * 海清人员信息下发数据打包（卡片）
     * 用于修改，修改的时候，人脸图片等不需要下发
     * TODO 增加判断所属用户是否有图片，没有图片使用默认图片
     *
     * @param dCard
     * @return
     */
    private HQInfoDTO transferHQInfoDTO(DCard dCard) {
        HQInfoDTO dto = new HQInfoDTO();
        User user = userService.selectUserById(dCard.getUserId());
        if (StringUtils.isNotEmpty(user.getFaceUrl())) {
            dto.setPicURI(user.getFaceUrl());
        } else {
            dto.setPicURI(hqDefaultPic);
        }
        dto.setCustomId(dCard.getCustomId());
        dto.setPersonType(0);
        dto.setRFIDCard(dCard.getCardSn());
        dto.setRFCardMode(0);
        if (null != dCard.getDoorEndDate()) {
            //时间段有效
            dto.setTempCardType(1);
            dto.setCardValidBegin(null != dCard.getDoorBeginDate() ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dCard.getDoorBeginDate()) : null);
            dto.setCardValidEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dCard.getDoorEndDate()));
        } else {
            dto.setTempCardType(0);
        }
        dto.setAddress(dCard.getFloorCode());
        return dto;
    }

    private HQInfoDTO transferHQInfoDTO(Visitor visitor) {

        HQInfoDTO dto = new HQInfoDTO();

        dto.setCustomId(visitor.getCustomId());
        dto.setName(visitor.getVisitorName());
        dto.setPersonType(visitor.getPersonType());
        dto.setTempCardType(Integer.parseInt(visitor.getVisitorType()));
        dto.setPicURI(visitor.getFaceUrl());
        if ("1".equals(visitor.getVisitorType()) || "2".equals(visitor.getVisitorType())) {
            dto.setCardValidBegin(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, visitor.getStartTime()));
            dto.setCardValidEnd(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, visitor.getEndTime()));
        } else if ("3".equals(visitor.getVisitorType())) {
            dto.setEffectNumber(Math.toIntExact(visitor.getEffectNumber()));
        }

        return dto;
    }

    /**
     * @description: 获取设备下发状态
     * @author caogq
     * @date: 2022/3/18 19:14
     * @Param
     */
    public Object getRecStatus(String className, List<String> deviceSns, List<String> customIds, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandGetRecStatus, version);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("class_name", className);
        dataObj.put("customIds", customIds);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 单个删除人员
     * @author caogq
     * @date: 2022/3/18 19:12
     * @Param
     */
    public Object delUserInfos(List<String> deviceSns, Map<String, String> customId, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUserDelete, version);
        JSONObject dataObj = new JSONObject();

        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        dataObj.put("info", customId);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 批量删除人员
     * @author caogq
     * @date: 2022/3/18 19:12
     * @Param
     */
    public Object delBatchUserInfos(List<String> deviceSns, Map<String, List<String>> customIds, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDelete, version);
        JSONObject dataObj = new JSONObject();
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        dataObj.put("info", customIds);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 批量删除人员
     * @author caogq
     * @date: 2022/3/18 19:12
     * @Param
     */
    public Object delBatchVisitorInfos(List<String> deviceSns, Map<String, List<String>> customIds, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDelete, version);
        JSONObject dataObj = new JSONObject();
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        dataObj.put("info", customIds);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 远程开门-海清
     * @author caogq
     * @date: 2022/3/18 19:14
     */
    public Object openDoor(String devSn, String type, String version) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandOpenDoor, version);
        JSONObject dataObj = new JSONObject();
        dataObj.put("deviceCode", devSn);
        dataObj.put("type", type);
        HQOpenDoorInfoDTO hqOpenDoorInfoDTO = new HQOpenDoorInfoDTO();
        hqOpenDoorInfoDTO.setFacesluiceId(devSn);
        hqOpenDoorInfoDTO.setOpenDoor(1);
        hqOpenDoorInfoDTO.setShowInfo("请通行");
        dataObj.put("info", hqOpenDoorInfoDTO);
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    /**
     * @description: 远程重启
     * @author caogq
     * @date: 2022/3/18 19:12
     */
    public Object reboot(String devSn) {
        JSONObject obj = getBaseObj(AccessServiceName.reboot, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        dataObj.put("deviceCode", devSn);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        dataObj.put("info", "");
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }


    /** =================================================================== 物业用户下发相关 ============================================================= */

    public Object downBatchEstateUserInfos(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceEstateUserInfoDtos = transferHQDeviceEstateUserDTO(accessDevices, users);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceEstateUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    private List<HQDeviceUserInfoDto> transferHQDeviceEstateUserDTO(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (EstateUserDownDTO user : users) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(user.getCustomId());
                dto.setName(user.getUserName());
                dto.setPersonType(0);
                dto.setTempCardType(0);
                dto.setPicURI(user.getFaceUrl());
                dto.setAddress("8,40");
                hqInfoDTOS.add(dto);
            }
            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }
        return hqDeviceUserInfoDtos;
    }

    public Object downBatchEstateUserCardInfos(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceEstateUserInfoDtos = transferHQDeviceEstateUserCardDTO(accessDevices, users);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceEstateUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    private List<HQDeviceUserInfoDto> transferHQDeviceEstateUserCardDTO(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (EstateUserDownDTO user : users) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(user.getCardCustomId());
                dto.setName(user.getUserName());
                dto.setPersonType(0);
                dto.setTempCardType(0);
                dto.setPicURI(hqDefaultPic);
                dto.setRFCardMode(0);
                dto.setRFIDCard(user.getCardSn());
                dto.setAddress("8,40");
                hqInfoDTOS.add(dto);
            }
            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }
        return hqDeviceUserInfoDtos;
    }

    public Object downBatchEstateUserAndCardInfos(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users, List<EstateUserDownDTO> cards) {
        JSONObject obj = getBaseObj(AccessServiceName.CommandUsersDownload, AccessCommandConstant.VERSION);
        JSONObject dataObj = new JSONObject();
        List<String> deviceSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        dataObj.put("deviceCodes", deviceSns);
        dataObj.put("type", AccessCommandConstant.DeviceType.HQ);
        List<HQDeviceUserInfoDto> hqDeviceEstateUserInfoDtos = transferHQDeviceEstateUserAndCardDTO(accessDevices, users, cards);
        /***增加卡片信息的下发****/
        dataObj.put("info", JSONObject.toJSONString(hqDeviceEstateUserInfoDtos));
        obj.put(ApiConstant.DATA, dataObj);
        Map<String, Object> params = JSONObject.toJavaObject(obj, Map.class);
        Object o = restTemplateUtils.httpPostJson(apiUrl, params, null, String.class);
        return o;
    }

    private List<HQDeviceUserInfoDto> transferHQDeviceEstateUserAndCardDTO(List<AccessDevice> accessDevices, List<EstateUserDownDTO> users, List<EstateUserDownDTO> cards) {
        List<HQDeviceUserInfoDto> hqDeviceUserInfoDtos = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            HQDeviceUserInfoDto hqDeviceUserInfoDto = new HQDeviceUserInfoDto();
            List<HQInfoDTO> hqInfoDTOS = new ArrayList<>();
            for (EstateUserDownDTO user : users) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(user.getCustomId());
                dto.setName(user.getUserName());
                dto.setPersonType(0);
                dto.setTempCardType(0);
                dto.setPicURI(user.getFaceUrl());
                dto.setAddress("8,40");
                hqInfoDTOS.add(dto);
            }
            for (EstateUserDownDTO user : cards) {
                HQInfoDTO dto = new HQInfoDTO();
                dto.setCustomId(user.getCardCustomId());
                dto.setName(user.getUserName());
                dto.setPersonType(0);
                dto.setTempCardType(0);
                dto.setPicURI(hqDefaultPic);
                dto.setRFCardMode(0);
                dto.setRFIDCard(user.getCardSn());
                dto.setAddress("8,40");
                hqInfoDTOS.add(dto);
            }
            hqDeviceUserInfoDto.setDeviceCode(accessDevice.getDevSn());
            hqDeviceUserInfoDto.setHqInfoDtos(hqInfoDTOS);
            hqDeviceUserInfoDtos.add(hqDeviceUserInfoDto);
        }
        return hqDeviceUserInfoDtos;
    }
}
